package HashMap.Nodo.Operaciones;

import HashMap.GenerarCodigoNASM;
import HashMap.Pila;
import HashMap.Nodo.Categoria;
import HashMap.Nodo.Nodo;
import HashMap.Nodo.Operacion;
import HashMap.Nodo.Subclases.Escalar;
import HashMap.Nodo.TipoBasicoDeDatos;

public class OperacionesComparativas implements Operacion {

    private final Nodo nodo1;
    private final Nodo nodo2;
    private Nodo nodoFinal;
    private String operacion;

    public OperacionesComparativas(Nodo nodo1, Nodo nodo2) {
        this.nodo1 = nodo1;
        this.nodo2 = nodo2;
    }

    @Override
    public int getLongitud() {
        throw new UnsupportedOperationException("Operacion no soportada");
    }

    @Override
    public String generarCodigoNASM() {
        switch (operacion) {
            case "IGUALIGUAL":
                return generarCodigoNASMigualdad();
            case "DISTINTODE":
                return generarCodigoNASMdesigualdad();
            case "MENORQUEIGUAL":
                return generarCodigoNASMmenorIgualQue();
            case "MAYORQUEIGUAL":
                return generarCodigoNASMmayorIgualQue();
            case "MENORQUE":
                return generarCodigoNASMmenorQue();
            case "MAYORQUE":
                return generarCodigoNASMmayorQue();
            default:
                return null;
        }
    }

    @Override
    public Nodo generarNodo(String tokenOperacion) {
        switch (tokenOperacion) {
            case "IGUALIGUAL":
                return igualdad();
            case "DISTINTODE":
                return desigualdad();
            case "MENORQUEIGUAL":
                return menorIgualQue();
            case "MAYORQUEIGUAL":
                return mayorIgualQue();
            case "MENORQUE":
                return menorQue();
            case "MAYORQUE":
                return mayorQue();
            default:
                return null;
        }
    }

    public String generarCodigoNASMigualdad() {
        return "eq [" + nodo1.getNombre() + "], [" + nodo2.getNombre() + "]\n"
                + "mov [" + nodoFinal.getNombre() + "], aux";
    }

    public String generarCodigoNASMdesigualdad() {
        return "neq [" + nodo1.getNombre() + "], [" + nodo2.getNombre() + "]\n"
                + "mov [" + nodoFinal.getNombre() + "], aux";
    }

    public String generarCodigoNASMmenorIgualQue() {
        return "leq [" + nodo1.getNombre() + "], [" + nodo2.getNombre() + "]\n"
                + "mov [" + nodoFinal.getNombre() + "], aux";
    }

    public String generarCodigoNASMmayorIgualQue() {
        return "geq [" + nodo1.getNombre() + "], [" + nodo2.getNombre() + "]\n"
                + "mov [" + nodoFinal.getNombre() + "], aux";
    }

    public String generarCodigoNASMmenorQue() {
        return "lst [" + nodo1.getNombre() + "], [" + nodo2.getNombre() + "]\n"
                + "mov [" + nodoFinal.getNombre() + "], aux";
    }

    public String generarCodigoNASMmayorQue() {
        return "grt [" + nodo1.getNombre() + "], [" + nodo2.getNombre() + "]\n"
                + "mov [" + nodoFinal.getNombre() + "], aux";
    }

    private boolean cumpleCondiciones(Nodo nodo1, Nodo nodo2) {
        return (nodo1.getTipoBasicoDeDatos() == TipoBasicoDeDatos.INT
                || nodo1.getTipoBasicoDeDatos() == TipoBasicoDeDatos.FLOAT)
                && (nodo2.getTipoBasicoDeDatos() == TipoBasicoDeDatos.INT
                || nodo2.getTipoBasicoDeDatos() == TipoBasicoDeDatos.FLOAT)
                && (nodo1.getNivelDeIndireccion() == 0
                || nodo1.getNivelDeIndireccion() == 1)
                && (nodo2.getNivelDeIndireccion() == 0
                || nodo2.getNivelDeIndireccion() == 1);

    }

    private Nodo igualdad() {

        if (cumpleCondiciones(nodo1, nodo2)) {
            operacion = "IGUALIGUAL";
            return rellenarNodoFinal();
        } else {
            throw new IllegalArgumentException("No se cumplen las condiciones para realizar la igualdad");
        }

    }

    private Nodo desigualdad() {
        if (cumpleCondiciones(nodo1, nodo2)) {
            operacion = "DISTINTODE";
            return rellenarNodoFinal();
        } else {
            throw new IllegalArgumentException("No se cumplen las condiciones para realizar la desigualdaD");
        }
    }

    private Nodo menorIgualQue() {
        if (cumpleCondiciones(nodo1, nodo2)) {
            operacion = "MENORQUEIGUAL";
            return rellenarNodoFinal();
        } else {
            throw new IllegalArgumentException("No se cumplen las condiciones para realizar la comparacion");
        }
    }

    private Nodo mayorIgualQue() {
        if (cumpleCondiciones(nodo1, nodo2)) {
            operacion = "MAYORQUEIGUAL";
            return rellenarNodoFinal();
        } else {
            throw new IllegalArgumentException("No se cumplen las condiciones para realizar la comparacion");
        }
    }

    private Nodo menorQue() {
        if (cumpleCondiciones(nodo1, nodo2)) {
            operacion = "MENORQUE";
            return rellenarNodoFinal();
        } else {
            throw new IllegalArgumentException("No se cumplen las condiciones para realizar la comparacion");
        }
    }

    private Nodo mayorQue() {
        if (cumpleCondiciones(nodo1, nodo2)) {
            operacion = "MAYORQUE";
            return rellenarNodoFinal();
        } else {
            throw new IllegalArgumentException("No se cumplen las condiciones para realizar la comparacion");
        }
    }

    private Nodo rellenarNodoFinal() {
        GenerarCodigoNASM generador = GenerarCodigoNASM.getInstancia();
        String nombre = generador.getNombreVariableAuxiliar();
        nodoFinal = new Escalar(nombre, TipoBasicoDeDatos.BOOLEAN, Categoria.VARIABLE, 0, operacion);
        Pila.getInstancia().addNodoALaTablaSuperior(nodoFinal);
        return nodoFinal;
    }
}
